bitkeeper revision 1.33.1.1 (3e4d0046UBuDSsmiQzTssLuipi89Wg)
authorsmh22@boulderdash.cl.cam.ac.uk <smh22@boulderdash.cl.cam.ac.uk>
Fri, 14 Feb 2003 14:42:14 +0000 (14:42 +0000)
committersmh22@boulderdash.cl.cam.ac.uk <smh22@boulderdash.cl.cam.ac.uk>
Fri, 14 Feb 2003 14:42:14 +0000 (14:42 +0000)
put domain builder tools and scripts under bk
(these are for running under domain 0)

12 files changed:
.rootkeys
tools/domain_builder/Makefile [new file with mode: 0644]
tools/domain_builder/README [new file with mode: 0644]
tools/domain_builder/dom0_defs.h [new file with mode: 0644]
tools/domain_builder/dom0_ops.h [new file with mode: 0644]
tools/domain_builder/dom_builder.c [new file with mode: 0644]
tools/domain_builder/dom_kill.c [new file with mode: 0644]
tools/domain_builder/hypervisor_defs.h [new file with mode: 0644]
tools/domain_builder/mem_defs.h [new file with mode: 0644]
tools/domain_builder/newdom [new file with mode: 0644]
tools/domain_builder/vifinit [new file with mode: 0644]
xen-2.4.16/arch/i386/apic.o [new file with mode: 0644]

index fbeff2f687a184a8770c461072756e205ed362ee..7fbe8db286b504202eb14690f699b879050556be 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
@@ -1,12 +1,23 @@
 3ddb6b0bKlMz_dz-M59a1mkUa1lASw BitKeeper/etc/config
 3ddb6b0buTaC5zg1_a8FoAR9FWi_mw BitKeeper/etc/ignore
 3ddb79c9_hgSp-gsQm8HqWM_9W3B_A BitKeeper/etc/logging_ok
+3e4d00468-FN2VDeEHo96zxrMHK_mA tools/domain_builder/Makefile
+3e4d0046SPau_y0sw2WLJz8QkqNoRA tools/domain_builder/README
+3e4d0046bbdH0GsI9J_1Eb4ZQHfIiQ tools/domain_builder/dom0_defs.h
+3e4d0046RgYCfGOw6qGz_7kYLMV2Vw tools/domain_builder/dom0_ops.h
+3e4d0046ouLij_CMN_j7-dUHZIBI_A tools/domain_builder/dom_builder.c
+3e4d0046EKs06fY0CWDEgZQcn7DYUg tools/domain_builder/dom_kill.c
+3e4d0046aPbGiRTtdWxqY5b3ytWurA tools/domain_builder/hypervisor_defs.h
+3e4d00468aE86IfyjfrJwYoxzM7pAw tools/domain_builder/mem_defs.h
+3e4d0046VHhXwFuG5FK34AVxqd5A_A tools/domain_builder/newdom
+3e4d0046IBzDIeaMbQB-e2QB2ahbig tools/domain_builder/vifinit
 3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen-2.4.16/Makefile
 3ddb79bcCa2VbsMp7mWKlhgwLQUQGA xen-2.4.16/README
 3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen-2.4.16/Rules.mk
 3ddb79bcZbRBzT3elFWSX7u6NtMagQ xen-2.4.16/arch/i386/Makefile
 3ddb79bcBQF85CfLS4i1WGZ4oLLaCA xen-2.4.16/arch/i386/Rules.mk
 3ddb79bcsjinG9k1KcvbVBuas1R2dA xen-2.4.16/arch/i386/apic.c
+3e4d0046IHluXnd2lSLBCKqMg2QsZg xen-2.4.16/arch/i386/apic.o
 3ddb79bcSC_LvnmFlX-T5iTgaR0SKg xen-2.4.16/arch/i386/boot/boot.S
 3ddb79bcUrk2EIaM5VsT6wUudH1kkg xen-2.4.16/arch/i386/delay.c
 3ddb79bcecupHj56ZbTa3B0FxDowMg xen-2.4.16/arch/i386/entry.S
diff --git a/tools/domain_builder/Makefile b/tools/domain_builder/Makefile
new file mode 100644 (file)
index 0000000..6707481
--- /dev/null
@@ -0,0 +1,17 @@
+CC = gcc
+BUILDER = domain_builder
+KILL = kill_domain
+
+all: dom_builder.o dom_kill.o
+       $(CC) -o $(BUILDER) dom_builder.o
+       $(CC) -o $(KILL) dom_kill.o
+
+dom_builder.o: dom_builder.c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h
+       $(CC) -c dom_builder.c 
+
+dom_kill.o: dom_kill.c dom0_ops.h dom0_defs.h
+       $(CC) -c dom_kill.c 
+
+clean:
+       $(RM) *.o domain_builder kill_domain
+
diff --git a/tools/domain_builder/README b/tools/domain_builder/README
new file mode 100644 (file)
index 0000000..7622ead
--- /dev/null
@@ -0,0 +1,29 @@
+A couple of simple steps to get you going:
+
+1. do make (suitable Makefile is in the source dir)
+2. copy over andy's vifinit script to local dir
+3. copy over xenolinux guestos image (NB. image needs to be uncompressed, so
+if the only image you have is image.gz do gunzip image.gz before doing 
+anything further)
+4. add executable permissions to newdom and vifint
+5. edit newdom script and change it as it suits you
+
+newdom script takes guestos image file name as first parameter and newdom id
+as second parameter, eg.:
+
+./newdom xenolinux 1
+
+should initiate building of dom1 with the image contained in file named 
+xenolinux in local dir.
+
+in general, domain_builder application takes three parameters: requested 
+memory in kb, guestos image file name and number of vifs to be created, eg.
+
+./domain_builder 16000 xenolinux 1
+
+would build domX reserving 16MB mem, creating 1 vif and using os image stored
+as xenolinux in local dir.
+
+happy booting!
+
+boris
diff --git a/tools/domain_builder/dom0_defs.h b/tools/domain_builder/dom0_defs.h
new file mode 100644 (file)
index 0000000..bba0204
--- /dev/null
@@ -0,0 +1,8 @@
+#define PROC_XENO_ROOT  "xeno"
+#define PROC_CMD        "dom0_cmd"
+#define PROC_DOM_PREFIX "dom"
+#define PROC_DOM_MEM    "mem"
+#define PROC_DOM_DATA   "new_dom_data"
+
+#define MAX_PATH        256
+
diff --git a/tools/domain_builder/dom0_ops.h b/tools/domain_builder/dom0_ops.h
new file mode 100644 (file)
index 0000000..d98ce1b
--- /dev/null
@@ -0,0 +1,80 @@
+/******************************************************************************
+ * dom0_ops.h
+ * 
+ * Process command requests from domain-0 guest OS.
+ * 
+ * Copyright (c) 2002, K A Fraser, B Dragovic
+ */
+
+#define DOM0_NEWDOMAIN   0
+#define DOM0_KILLDOMAIN  1
+#define DOM0_GETMEMLIST  2
+#define DOM0_STARTDOM    4
+#define MAP_DOM_MEM      6 /* Not passed down to Xen */
+#define DO_PGUPDATES     7 /* Not passed down to Xen */
+#define MAX_CMD          8
+
+#define MAX_CMD_LEN     256
+
+typedef struct dom0_newdomain_st
+{
+    unsigned int domain;
+    unsigned int memory_kb;
+    unsigned int num_vifs;  // temporary
+    unsigned long pg_head;  // return parameter
+} dom0_newdomain_t;
+
+typedef struct dom0_killdomain_st
+{
+    unsigned int domain;
+} dom0_killdomain_t;
+
+typedef struct dom0_getmemlist_st
+{
+    unsigned long start_pfn;
+    unsigned long num_pfns;
+    void *buffer;
+} dom0_getmemlist_t;
+
+/* This is entirely processed by XenoLinux */
+typedef struct dom_mem 
+{
+    unsigned int domain;
+    unsigned long vaddr;
+    unsigned long start_pfn;
+    int tot_pages;
+} dom_mem_t;
+
+/* This is entirely processed by XenoLinux */
+typedef struct dom_pgupdate
+{
+    unsigned long pgt_update_arr;
+    unsigned long num_pgt_updates;
+} dom_pgupdate_t;
+
+typedef struct domain_launch
+{
+    unsigned int domain;
+    unsigned long l2_pgt_addr;
+    unsigned long virt_load_addr;
+    unsigned long virt_shinfo_addr;
+    unsigned long virt_startinfo_addr;
+    unsigned int num_vifs;
+    char cmd_line[MAX_CMD_LEN];
+} dom_meminfo_t;
+
+typedef struct dom0_op_st
+{
+    unsigned long cmd;
+    union
+    {
+        dom0_newdomain_t newdomain;
+        dom0_killdomain_t killdomain;
+        dom0_getmemlist_t getmemlist;
+        dom_mem_t dommem;
+        dom_pgupdate_t pgupdate;
+        dom_meminfo_t meminfo;
+    }
+    u;
+} dom0_op_t;
+
diff --git a/tools/domain_builder/dom_builder.c b/tools/domain_builder/dom_builder.c
new file mode 100644 (file)
index 0000000..4e39068
--- /dev/null
@@ -0,0 +1,485 @@
+/* 
+ * XenoDomainBuilder, copyright (c) Boris Dragovic, bd240@cl.cam.ac.uk
+ * This code is released under terms and conditions of GNU GPL :).
+ * Usage: <executable> <mem_kb> <os image> <num_vifs> 
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "hypervisor_defs.h"
+#include "dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+#define PERR_STRING "Xeno Domain Builder"
+
+#define GUEST_SIG   "XenoGues"
+#define SIG_LEN    8
+
+#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED)
+#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED|_PAGE_DIRTY)
+
+/* standardized error reporting function */
+static void dberr(char *msg)
+{
+    printf("%s: %s\n", PERR_STRING, msg);
+}
+
+/* status reporting function */
+static void dbstatus(char * msg)
+{
+    printf("Domain Builder: %s\n", msg);
+}
+
+/* clean up domain's memory allocations */
+static void dom_mem_cleanup(dom_mem_t * dom_mem)
+{
+    char mem_path[MAX_PATH];
+    int mem_fd;
+
+    /* open the domain's /proc mem interface */
+    sprintf(mem_path, "%s%s%s%s%d%s%s", "/proc/", PROC_XENO_ROOT, "/", 
+        PROC_DOM_PREFIX, dom_mem->domain, "/", PROC_DOM_MEM);
+
+    mem_fd = open(mem_path, O_WRONLY);
+    if(mem_fd < 0){
+        perror(PERR_STRING);
+    }
+
+       if(write(mem_fd, (dom_mem_t *)dom_mem, sizeof(dom_mem_t)) < 0){
+               dbstatus("Error unmapping domain's memory.\n");
+       }
+
+    close(mem_fd);
+}
+
+/* ask dom0 to export domains memory through /proc */
+static int setup_dom_memmap(unsigned long pfn, int pages, int dom)
+{
+    char cmd_path[MAX_PATH];
+    dom0_op_t dop;
+    int cmd_fd;
+
+    dop.cmd = MAP_DOM_MEM;
+    dop.u.dommem.start_pfn = pfn;
+    dop.u.dommem.tot_pages = pages;
+    dop.u.dommem.domain = dom;
+
+    /* open the /proc command interface */
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    cmd_fd = open(cmd_path, O_WRONLY);
+    if(cmd_fd < 0){
+        perror(PERR_STRING);
+        return -1;
+    }
+
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+    close(cmd_fd);
+
+    return 0;
+}
+      
+/* request the actual mapping from dom0 */
+static unsigned long get_vaddr(unsigned int dom)
+{
+    char mem_path[MAX_PATH];
+       unsigned long addr;
+    int mem_fd;
+
+    /* open the domain's /proc mem interface */
+    sprintf(mem_path, "%s%s%s%s%d%s%s", "/proc/", PROC_XENO_ROOT, "/", 
+                    PROC_DOM_PREFIX, dom, "/", PROC_DOM_MEM);
+
+    mem_fd = open(mem_path, O_RDONLY);
+    if(mem_fd < 0){
+        perror(PERR_STRING);
+        return 0;
+    }
+
+    /* get virtual address of mapped region */
+       read(mem_fd, &addr, sizeof(addr));
+       
+    close(mem_fd);
+
+    return addr;
+}
+
+static int map_dom_mem(unsigned long pfn, int pages, int dom, 
+    dom_mem_t * dom_mem)
+{
+
+    if(setup_dom_memmap(pfn, pages, dom)){
+        perror(PERR_STRING);
+        return -1;
+    }
+
+    dom_mem->domain = dom;
+    dom_mem->start_pfn = pfn;
+    dom_mem->tot_pages = pages;
+    if((dom_mem->vaddr = get_vaddr(dom)) == 0){
+        dberr("Error mapping dom memory.");
+        return -1;
+    }
+    
+    return 0;
+}
+
+/* create new domain */
+static dom0_newdomain_t * create_new_domain(long req_mem)
+{
+    dom0_newdomain_t * dom_data;
+    char cmd_path[MAX_PATH];
+    char dom_id_path[MAX_PATH];
+    dom0_op_t dop;
+    int cmd_fd;
+    int id_fd;
+
+    /* open the /proc command interface */
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    cmd_fd = open(cmd_path, O_WRONLY);
+    if(cmd_fd < 0){
+        perror(PERR_STRING);
+        return 0;
+    }
+
+    dop.cmd = DOM0_NEWDOMAIN;
+    dop.u.newdomain.memory_kb = req_mem;
+
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+    close(cmd_fd);
+
+    sprintf(dom_id_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", 
+        PROC_DOM_DATA);
+    while((id_fd = open(dom_id_path, O_RDONLY)) < 0){}
+    dom_data = (dom0_newdomain_t *)malloc(sizeof(dom0_newdomain_t));
+    read(id_fd, dom_data, sizeof(dom0_newdomain_t));
+    close(id_fd);
+    
+    sprintf(cmd_path, "Reserved %ld kbytes memory and assigned id %d to the"
+                    "new domain.", req_mem, dom_data->domain);
+    dbstatus(cmd_path);
+
+    return dom_data;
+}    
+
+/* open kernel image and do some sanity checks */
+static int do_kernel_chcks(char *image, long dom_size, 
+    unsigned long * load_addr, size_t * ksize)
+{
+    char signature[8];
+    char status[MAX_PATH];
+    struct stat stat;
+    int fd;
+    int ret; 
+    
+    fd = open(image, O_RDONLY);
+    if(fd < 0){
+        perror(PERR_STRING);
+        ret = -1;    
+        goto out;
+    }
+
+    if(fstat(fd, &stat) < 0){
+        perror(PERR_STRING);
+        ret = -1;
+               close(fd);
+        goto out;
+    }
+
+    if(stat.st_size > (dom_size << 10)){
+        sprintf(status, "Kernel image size %ld larger than requested "
+            "domain size %ld\n Terminated.\n", stat.st_size, dom_size);
+        dberr(status);
+        ret = -1;
+               close(fd);
+        goto out;
+    }
+    *ksize = stat.st_size - SIG_LEN;
+    
+    read(fd, signature, SIG_LEN);
+    if(strncmp(signature, GUEST_SIG, SIG_LEN)){
+        dberr("Kernel image does not contain required signature. "
+               "Terminating.\n");
+        ret = -1;
+               close(fd);
+        goto out;
+    }
+
+    read(fd, load_addr, sizeof(unsigned long));
+
+    sprintf(status, "Kernel image %s valid, kernel virtual load address %lx", 
+        image, *load_addr);
+    dbstatus(status);
+
+    ret = fd;
+
+out:    
+    return ret;
+}
+
+/* this is the main guestos setup function,
+ * returnes domain descriptor structure to be used when launching
+ * the domain by hypervisor to do some last minute initialization.
+ * page table initialization is done by making a list of page table
+ * requests that are handeled by the hypervisor in the ordinary
+ * manner. this way, many potentially messy things are avoided...
+ */ 
+static dom_meminfo_t * setup_guestos(int dom, int kernel_fd, 
+    unsigned long virt_load_addr, size_t ksize, dom_mem_t *dom_mem)
+{
+    dom_meminfo_t * meminfo = (dom_meminfo_t *)malloc(sizeof(dom_meminfo_t));
+    unsigned long * page_array = (unsigned long *)(dom_mem->vaddr);
+    page_update_request_t * pgt_updates = (page_update_request_t *)
+        (dom_mem->vaddr + ((ksize + (PAGE_SIZE-1)) & PAGE_MASK));
+    dom_mem_t mem_map;
+    dom_meminfo_t * ret = NULL;
+    int alloc_index = dom_mem->tot_pages - 1, num_pt_pages;
+    unsigned long l2tab;
+    unsigned long l1tab = 0;
+    unsigned long num_pgt_updates = 0;
+    unsigned long pgt_update_arr = (unsigned long)pgt_updates;
+    unsigned long count, pt_start;
+
+    /* Count bottom-level PTs. Round up to a whole PT. */
+    num_pt_pages = 
+        (l1_table_offset(virt_load_addr) + dom_mem->tot_pages + 1023) / 1024;
+    /* We must also count the page directory. */
+    num_pt_pages++;
+
+    /* Index of first PT page. */
+    pt_start = dom_mem->tot_pages - num_pt_pages;
+
+    /* first allocate page for page dir. allocation goes backwards from the
+     * end of the allocated physical address space.
+     */
+    l2tab = *(page_array + alloc_index) << PAGE_SHIFT; 
+    alloc_index--;
+    meminfo->l2_pgt_addr = l2tab;
+    meminfo->virt_shinfo_addr = virt_load_addr + nr_2_page(dom_mem->tot_pages);
+    count = ((unsigned long)pgt_updates - (unsigned long)(dom_mem->vaddr)) 
+        >> PAGE_SHIFT;
+
+    /* zero out l2 page */
+    if(map_dom_mem(l2tab >> PAGE_SHIFT, 1, dom_mem->domain, &mem_map)){
+        dberr("Unable to map l2 page into Domain Builder.");
+        goto out;
+    }
+    memset((void *)mem_map.vaddr, 0, PAGE_SIZE);
+    dom_mem_cleanup(&mem_map);
+
+    /* pin down l2tab addr as page dir page - causes hypervisor to provide
+     * correct protection for the page
+     */ 
+    pgt_updates->ptr = l2tab | PGREQ_EXTENDED_COMMAND;
+    pgt_updates->val = PGEXT_PIN_L2_TABLE;
+    pgt_updates++;
+    num_pgt_updates++;
+
+    /* this loop initializes page tables and does one extra entry 
+     * to be used by the shared info page. shared info is not in
+     * the domains physical address space and is not owned by the
+     * domain.
+     */
+    l2tab += l2_table_offset(virt_load_addr) * sizeof(l2_pgentry_t);
+    for(count = 0;
+        count < dom_mem->tot_pages + 1; 
+        count++){
+        
+        if(!((unsigned long)l1tab & (PAGE_SIZE-1))){
+            l1tab = *(page_array + alloc_index) << PAGE_SHIFT;
+            alloc_index--;
+                       
+            /* zero out l1 page */
+            if(map_dom_mem(l1tab >> PAGE_SHIFT, 1, dom_mem->domain, &mem_map)){
+                dberr("Unable to map l1 page into Domain Builder.");
+                goto out;
+            }
+            memset((void *)mem_map.vaddr, 0, PAGE_SIZE);
+            dom_mem_cleanup(&mem_map);
+
+            l1tab += l1_table_offset(virt_load_addr + nr_2_page(count)) 
+                * sizeof(l1_pgentry_t);
+
+            /* make apropriate entry in the page directory */
+            pgt_updates->ptr = l2tab;
+            pgt_updates->val = l1tab | L2_PROT;
+            pgt_updates++;
+            num_pgt_updates++;
+            l2tab += sizeof(l2_pgentry_t);
+        }
+               
+        if ( count < pt_start )
+        {
+            pgt_updates->ptr = l1tab;
+            pgt_updates->val = (*(page_array + count) << PAGE_SHIFT) | L1_PROT;
+            pgt_updates++;
+            num_pgt_updates++;
+            l1tab += sizeof(l1_pgentry_t);
+        }
+        else
+        {
+            pgt_updates->ptr = l1tab;
+            pgt_updates->val = 
+               ((*(page_array + count) << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
+            pgt_updates++;
+            num_pgt_updates++;
+            l1tab += sizeof(l1_pgentry_t);
+        }
+
+        pgt_updates->ptr = 
+           (*(page_array + count) << PAGE_SHIFT) | PGREQ_MPT_UPDATE;
+        pgt_updates->val = count;
+        pgt_updates++;
+        num_pgt_updates++;
+    }
+
+    meminfo->virt_startinfo_addr = virt_load_addr + nr_2_page(alloc_index - 1);
+    meminfo->domain = dom;
+
+    /* copy the guest os image */
+    if(!(read(kernel_fd, (char *)dom_mem->vaddr, ksize) > 0)){
+        dberr("Error reading kernel image, could not"
+              " read the whole image. Terminating.\n");
+        goto out;
+    }
+
+    {
+        dom0_op_t pgupdate_req;
+        char cmd_path[MAX_PATH];
+        int cmd_fd;
+
+        sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+        if ( (cmd_fd = open(cmd_path, O_WRONLY)) < 0 ) goto out;
+
+        pgupdate_req.cmd = DO_PGUPDATES;
+        pgupdate_req.u.pgupdate.pgt_update_arr  = pgt_update_arr;
+        pgupdate_req.u.pgupdate.num_pgt_updates = num_pgt_updates;
+
+        write(cmd_fd, &pgupdate_req, sizeof(dom0_op_t));
+        close(cmd_fd);
+    }
+
+    ret = meminfo;
+out:
+
+    return ret;
+}
+
+static int launch_domain(dom_meminfo_t  * meminfo)
+{
+    char cmd_path[MAX_PATH];
+    dom0_op_t dop;
+    int cmd_fd;
+
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    cmd_fd = open(cmd_path, O_WRONLY);
+    if(cmd_fd < 0){
+        perror(PERR_STRING);
+        return -1;
+    }
+
+    dop.cmd = DOM0_STARTDOM;
+    memcpy(&dop.u.meminfo, meminfo, sizeof(dom_meminfo_t));
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+
+    dbstatus("Launched the new domain!");
+
+    close(cmd_fd);
+}
+
+int main(int argc, char **argv)
+{
+
+    dom0_newdomain_t * dom_data;
+    dom_mem_t dom_os_image;
+    dom_mem_t dom_pgt; 
+    dom_meminfo_t * meminfo;
+    size_t ksize;
+    unsigned long load_addr;
+    char status[1024];
+    int kernel_fd;
+    int count;
+    int cmd_len;
+    int ret = 0;
+
+       unsigned long addr;
+
+    if(argc < 4){
+        dberr("Usage: dom_builder <kbytes_mem> <image> <num_vifs> "
+                        "<boot_params>\n");
+        ret = -1;
+        goto out;
+    }
+
+    /* create new domain and set up all the neccessary mappings */
+
+    kernel_fd = do_kernel_chcks(argv[2], atol(argv[1]), &load_addr, &ksize);
+    if(kernel_fd < 0){
+        ret = -1;
+        goto out;
+    }
+
+    /* request the creation of new domain */
+    dom_data = create_new_domain(atol(argv[1]));
+    if(dom_data == 0){
+        ret = -1;
+        goto out;
+    }
+
+    /* map domain's memory */
+    if(map_dom_mem(dom_data->pg_head, dom_data->memory_kb >> (PAGE_SHIFT - 10), 
+        dom_data->domain, &dom_os_image)){
+        ret = -1;
+        goto out;
+    }
+
+    /* the following code does the actual domain building */
+    meminfo = setup_guestos(dom_data->domain, kernel_fd, load_addr, ksize, 
+        &dom_os_image);
+    if(meminfo == NULL){
+               printf("Domain Builder: debug: meminfo NULL\n");
+        ret = -1;
+        dom_mem_cleanup(&dom_os_image);
+        goto out;
+    }
+
+    dom_mem_cleanup(&dom_os_image);
+
+    meminfo->virt_load_addr = load_addr;
+    meminfo->num_vifs = atoi(argv[3]);
+    meminfo->cmd_line[0] = '\0';
+    cmd_len = 0;
+    for(count = 4; count < argc; count++){
+        if(cmd_len + strlen(argv[count]) > MAX_CMD_LEN - 1){
+            dberr("Size of image boot params too big!\n");
+            break;
+        }
+        strcat(meminfo->cmd_line, argv[count]);
+        strcat(meminfo->cmd_line, " ");
+        cmd_len += strlen(argv[count] + 1);
+    }
+
+    sprintf(status, 
+           "About to launch new domain %d with folowing parameters:\n"
+           " * page table base: %lx \n * load address: %lx \n"
+           " * shared info address: %lx \n * start info address: %lx \n"
+           " * number of vifs: %d \n * cmd line: %s \n", meminfo->domain, 
+           meminfo->l2_pgt_addr, meminfo->virt_load_addr, 
+           meminfo->virt_shinfo_addr, meminfo->virt_startinfo_addr, 
+           meminfo->num_vifs, meminfo->cmd_line);
+    dbstatus(status);
+    
+    /* and launch the domain */
+    if(launch_domain(meminfo) != 0)
+       ret = -1;
+
+    free(meminfo);
+out:
+    return ret;
+}
diff --git a/tools/domain_builder/dom_kill.c b/tools/domain_builder/dom_kill.c
new file mode 100644 (file)
index 0000000..2b8b0a5
--- /dev/null
@@ -0,0 +1,55 @@
+/* 
+ * A very(!) simple program to kill a domain. (c) Boris Dragovic
+ * Usage: <executable> <mem_kb> <os image> <num_vifs> 
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "dom0_ops.h"
+#include "dom0_defs.h"
+
+#define PERR_STRING "Xen Domain Killer"
+
+static int do_kill_domain(int dom_id)
+{
+    char cmd_path[MAX_PATH];
+    dom0_op_t dop;
+    int cmd_fd;
+
+    dop.cmd = DOM0_KILLDOMAIN;
+    dop.u.killdomain.domain = dom_id;
+
+    /* open the /proc command interface */
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    cmd_fd = open(cmd_path, O_WRONLY);
+    if(cmd_fd < 0){
+        perror(PERR_STRING);
+        return -1;
+    }
+
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+    close(cmd_fd);
+
+    return 0;
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    if(argc < 2){
+        printf("Usage: kill_domain <domain_id>\n");
+        ret = -1;
+        goto out;
+    }
+
+    ret = do_kill_domain(atoi(argv[1]));
+
+out:
+    return ret;
+}
diff --git a/tools/domain_builder/hypervisor_defs.h b/tools/domain_builder/hypervisor_defs.h
new file mode 100644 (file)
index 0000000..7d0aba0
--- /dev/null
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * hypervisor_defs.h
+ * 
+ * This needs to be kept in sync with Xen's pagetable update interface!
+ * 
+ * Copyright (c) 2002-2003, Keir Fraser & Boris Dragovic 
+ */
+
+/* taken from include/hypervisor-ifs/hypervisor-if.h */
+typedef struct
+{
+/*
+ * PGREQ_XXX: specified in least-significant bits of 'ptr' field. All requests 
+ * specify relevent PTE or PT address in 'ptr'. Normal requests specify update 
+ * value in 'value'. Extended requests specify command in least 8 bits of 
+ * 'value'.
+ */
+    unsigned long ptr, val; /* *ptr = val */
+} page_update_request_t;
+
+/* A normal page-table update request. */
+#define PGREQ_NORMAL           0
+#define PGREQ_MPT_UPDATE 1
+/* An extended command. */
+#define PGREQ_EXTENDED_COMMAND 2
+/* Announce a new top-level page table. */
+#define PGEXT_PIN_L1_TABLE      0
+#define PGEXT_PIN_L2_TABLE      1
+#define PGEXT_PIN_L3_TABLE      2
+#define PGEXT_PIN_L4_TABLE      3
+#define PGEXT_UNPIN_TABLE       4
+#define PGEXT_NEW_BASEPTR       5
+#define PGEXT_TLB_FLUSH         6
+#define PGEXT_INVLPG            7
+#define PGEXT_CMD_MASK        255
+#define PGEXT_CMD_SHIFT         8
diff --git a/tools/domain_builder/mem_defs.h b/tools/domain_builder/mem_defs.h
new file mode 100644 (file)
index 0000000..a9a1441
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * memory related definitions needed for userspace domain builder dom0 application. these _need_ to
+ * be kept in sync with the kernel .h files they were copied over from or something horrible will
+ * happen. remmember: god kills a kitten every time you forget to keep these in sync.
+ * 
+ * KAF: Boris, these constants are all fixed by x86 hardware. So the kittens are safe for now :-)
+ * 
+ * Copyright 2002 by B Dragovic
+ */
+
+/* copied over from hypervisor: include/asm-i386/page.h */
+
+#define _PAGE_PRESENT   0x001
+#define _PAGE_RW    0x002
+#define _PAGE_USER  0x004
+#define _PAGE_PWT   0x008
+#define _PAGE_PCD   0x010
+#define _PAGE_ACCESSED  0x020
+#define _PAGE_DIRTY 0x040
+#define _PAGE_PAT       0x080
+#define _PAGE_PSE   0x080
+#define _PAGE_GLOBAL    0x100
+
+
+#define L1_PAGETABLE_SHIFT       12
+#define L2_PAGETABLE_SHIFT       22
+#define ENTRIES_PER_L1_PAGETABLE 1024
+#define ENTRIES_PER_L2_PAGETABLE 1024
+#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
+#define PAGE_SIZE               (1UL << PAGE_SHIFT)
+#define PAGE_MASK               (~(PAGE_SIZE-1))
+
+typedef struct { unsigned long l1_lo; } l1_pgentry_t;
+typedef struct { unsigned long l2_lo; } l2_pgentry_t;
+
+#define l1_table_offset(_a) \
+          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
+#define l2_table_offset(_a) \
+          ((_a) >> L2_PAGETABLE_SHIFT)
+
+/* local definitions */
+
+#define nr_2_page(x) (x << PAGE_SHIFT)
diff --git a/tools/domain_builder/newdom b/tools/domain_builder/newdom
new file mode 100644 (file)
index 0000000..979661e
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+VIFINIT=./vifinit
+DOM_BUILDER=./domain_builder
+
+DOM=$2
+
+ADDR=`/sbin/ifconfig eth0 | grep inet.addr | sed -e 's/.*inet addr:\([0-9.]*\) .*/\1/'`
+
+LO=`echo $ADDR | sed -e 's/[0-9]\+\.[0-9]\+\.[0-9]\+\.\([0-9]\+\)/\1/'`
+HI=`echo $ADDR | sed -e 's/\([0-9]\+\.[0-9]\+\.[0-9]\+\)\.[0-9]\+/\1/'`
+
+NEWADDR=$HI.$[LO+DOM]
+
+$VIFINIT $DOM $NEWADDR
+
+$DOM_BUILDER 16000 $1 1
diff --git a/tools/domain_builder/vifinit b/tools/domain_builder/vifinit
new file mode 100644 (file)
index 0000000..58b50ea
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# vifinit 
+#
+# This is a silly little script to dump a couple of simple rules down to 
+# the hypervisor to assign a full static IP to a given virtual interface.
+# 
+# Usage is:
+#
+#   vifinit [vif id] [dotted decimal ip address]
+#
+if [ $# -ne 2 ] ; 
+then
+        echo "usage: vifinit [vif id] [dotted decimal ip address]"
+        exit
+fi
+
+#outbound rule:
+echo "ADD ACCEPT srcaddr=$2 srcaddrmask=255.255.255.255 srcint=$1 dstint=-1 proto=any" > /proc/vfr
+
+#inbound rule:
+echo "ADD ACCEPT dstaddr=$2 dstaddrmask=255.255.255.255 srcint=-4 dstint=$1 proto=any" > /proc/vfr
+
+#----] done.
+
diff --git a/xen-2.4.16/arch/i386/apic.o b/xen-2.4.16/arch/i386/apic.o
new file mode 100644 (file)
index 0000000..deb15b2
Binary files /dev/null and b/xen-2.4.16/arch/i386/apic.o differ